package model.pieces;

import java.awt.Point;
import java.util.LinkedList;
import java.util.List;

import utils.PlayerSides;

import model.Board;

/**
 * Class represents a Pawn piece in chess game. A Pawn can move a single step forward to a free position or in diagonal (forward) to capture an opponent piece. 
 * On its first turn, a Pawn can also move two steps forward to a free position
 */
public class Pawn extends Piece {

	// member
	private boolean isFirstMove; // indicates if current move is Pawn's first
	
	// protected methods
	
	/**
	 * Gets reference to the game board and Pawn's current position on board.
	 * If it is Pawn's first move, returns positions within 1 or 2 steps, if free.
	 * Otherwise, returns position within 1 step ahead, if free.
	 * Returns the point ahead on board, if it is free
	 */
	@Override
	protected List<Point> getAvailableFreePositions(Board gameBoard, Point srcPoint) {
		
		// initialize free reachable positions list
		List<Point> freeList = new LinkedList<Point>();
		
		// check if position ahead exceeds board or already occupies another piece
		if (gameBoard.notValidPosition(srcPoint.x + getDirection(), srcPoint.y) || gameBoard.getPiece(srcPoint.x + getDirection(), srcPoint.y) != null) {
			return freeList;
		}
		
		// position within one step ahead is valid and free, add it to list		
		freeList.add(new Point(srcPoint.x + getDirection(), srcPoint.y));
		
		// check if current move is Pawn's first
		if (isFirstMove) {
			
			// check if 2 next positions exceed board or already occupies another piece			
			if (gameBoard.notValidPosition(srcPoint.x + getDirection(), srcPoint.y) || gameBoard.notValidPosition(srcPoint.x + 2*getDirection(), srcPoint.y) 
																					|| gameBoard.getPiece(srcPoint.x + getDirection(), srcPoint.y) != null 
																					|| gameBoard.getPiece(srcPoint.x + 2*getDirection(), srcPoint.y) != null) {
				// cannot move two steps
				return freeList;				
			}
			
			// position within 2 steps straight is valid and free, add it to list
			freeList.add(new Point(srcPoint.x + 2*getDirection(), srcPoint.y));
			// return list of position in range found
			return freeList;
		}
		
		// return list of position in range found
		return freeList;
	}
	
	/**
	 * Gets reference to the game board and Pawn's current position on board.
	 * If this is Pawn's first move, checks if positions within 2 steps in forward
	 * diagonal directions (right or left) hold opponent pieces. If so, they are returned.
	 * If not first turn, if forward-right or forward-left hold an enemy piece, they are returned
	 */
	@Override
	protected List<Point> getAvailableOpponentPositions(Board gameBoard, Point srcPoint) {
		
		// initialize list of reachable opponent's positions
		List<Point> opponentList = new LinkedList<Point>();
		

		// check if can capture forward pieces
		
		// check if first forward-aside position is valid
		if (gameBoard.isValidPosition(srcPoint.x + getDirection(), srcPoint.y + getDirection())) {
			
			// check if position holds a piece
			if (gameBoard.getPiece(srcPoint.x + getDirection(), srcPoint.y + getDirection()) != null) {
				
				// if piece is of rival team, conquer it
				if ( !super.sameSide(gameBoard.getPiece(srcPoint.x + getDirection(), srcPoint.y + getDirection())) ) {
					// add position to list
					opponentList.add(new Point(srcPoint.x + getDirection(), srcPoint.y + getDirection()));
				}	
			}
		}
		
		// check if second forward-aside position is valid
		if (gameBoard.isValidPosition(srcPoint.x + getDirection(), srcPoint.y - getDirection())) {
			
			// check if position holds a piece
			if (gameBoard.getPiece(srcPoint.x + getDirection(), srcPoint.y - getDirection()) != null) {
				
				// if piece is of rival team, conquer it
				if ( !super.sameSide(gameBoard.getPiece(srcPoint.x + getDirection(), srcPoint.y - getDirection())) ) {
					// add position to list
					opponentList.add(new Point(srcPoint.x + getDirection(), srcPoint.y - getDirection()));
				}	
			}
		}
		
		// return list of position in range found
		return opponentList;
	}
	
	// public methods	
	
	/**
	 * Constructor- creates a new Pawn assigned to given player
	 * @param side- indicates piece's player
	 */
	public Pawn(PlayerSides.Sides side) {
		
		// initialize values using base class's constructor
		super(side);
		
		// Pawn has not moved yet
		isFirstMove = true;
	}

	/**
	 * Returns a Pawn of the same team. Pawn's first move indicator is set as the same value
	 * of the Pawn being cloned
	 */
	@Override
	public Piece clone() {
		
		// create a new Pawn of the same team
		Pawn clonePawn = new Pawn(super.getPlayer());
		
		// set first move indicator
		clonePawn.isFirstMove = this.isFirstMove;
		
		// return the new Pawn
		return clonePawn;
	}
	
	/**
	 * Sets first-move-indicator as False, in order to check in the next turns only
	 * moves within a single step
	 */
	public void updateFirstMove() {	isFirstMove = false; }
}